package com.example.demo.udp;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.json.JSONUtil;
import com.example.demo.config.NettyClientSington;
import com.example.demo.config.ZuWangWebSocket;
import com.example.demo.controller.ConfigFileUtil;
import com.example.demo.pojo.BaseBean;
import com.example.demo.pojo.SendWebSocketInfo;
import com.example.demo.pojo.param.ParamReadResNew;
import com.example.demo.pojo.zuwang.autocheck.ZuWangAutoCheckFromJSRes;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @Description: UDP Netty 客户端事务处理器
 * @Author: junqiang.lu
 * @Date: 2023/8/25
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class DemoUdpNettyClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {

//    @Autowired
//    public ZuWangWebSocket zuWangWebSocket;


    /*
       客户端等待服务器的应答信息
     */
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket) throws Exception {
        // 读取数据
        ByteBuf byteBuf = datagramPacket.content();
        byte[] bytes = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(bytes);
        String response = new String(bytes,StandardCharsets.UTF_8);
        log.info("receive server msg:" + response);

        ConfigFileUtil configFileUtil = (ConfigFileUtil) NettyClientSington.beanFactory.getBean("configFileUtil");


        BaseBean bean = JSONUtil.toBean(response, BaseBean.class);
        //参数的请求
        if (bean.getTranstype().equals("1004")) {

            //判断是哪个设备
            switch (bean.getDevice()) {

                case "jicheng":
                    //新版读取
                    ParamReadResNew param_jiecheng = JSONUtil.toBean(response, ParamReadResNew.class);
                    //读取到新的了 然后更新param.json  告诉前端刷新界面
                    FileUtil.del(configFileUtil.param_jicheng_loc);
                    FileWriter jicheng_writer = new FileWriter(configFileUtil.param_jicheng_loc);
                    jicheng_writer.write(JSONUtil.toJsonStr(param_jiecheng));
                    bean.setUniStr(String.valueOf(UUID.randomUUID()));
                    sendInfo(bean);

                    break;
                case "YSRP":
                    //新版读取
                    ParamReadResNew paramJieshou = JSONUtil.toBean(response, ParamReadResNew.class);
                    //读取到新的了 然后更新param.json  告诉前端刷新界面
                    FileUtil.del(configFileUtil.param_jieshou_loc);
                    FileWriter paramJieshou_writer = new FileWriter(configFileUtil.param_jieshou_loc);
                    paramJieshou_writer.write(JSONUtil.toJsonStr(paramJieshou));
                    bean.setUniStr(String.valueOf(UUID.randomUUID()));
                    sendInfo(bean);


                    break;
                case "YIRC":
                    //新版读取
                    ParamReadResNew paramReadResNew = JSONUtil.toBean(response, ParamReadResNew.class);
                    //读取到新的了 然后更新param.json  告诉前端刷新界面
                    FileUtil.del(configFileUtil.param_remote_loc);
                    FileWriter remote_writer = new FileWriter(configFileUtil.param_remote_loc);
                    remote_writer.write(JSONUtil.toJsonStr(paramReadResNew));
                    bean.setUniStr(String.valueOf(UUID.randomUUID()));
                    sendInfo(bean);
                    break;

            }

        }//自检测
        else if (bean.getTranstype().equals("1006")) {

            //判断是哪个设备
            switch (bean.getDevice()) {

                case "YSRP":
                    updapteAutoCheck_jieshou(response, bean);
                    break;
                case "YIRC":
                    updapteAutoCheck_remoteControl(response, bean);
                    break;
            }
        }
        //自检测
        else if (bean.getTranstype().equals("1008")) {

            //判断是哪个设备
            switch (bean.getDevice()) {

                case "YSRP":
                    repairDevice_jieshou(response, bean);
                    break;
                case "YIRC":
                    repairDevice_remote(response, bean);
                    break;
            }
        }//ping
        else if (bean.getTranstype().equals("0002")) {

//            Iterator<Map.Entry<String, BaseBean>> iterator = DemoUdpNettyServerHandler.senderMap.entrySet().iterator();
//            int size = DemoUdpNettyServerHandler.senderMap.entrySet().size();
//            while (iterator.hasNext()){
//                Map.Entry<String, BaseBean> next = iterator.next();
//                if (!next.getKey().equals(bean.getDevice()) && size!=1){
//                    iterator.remove();
//                }
//            }
//            DemoUdpNettyServerHandler.senderMap.put(bean.getDevice(),bean);
//
//            //修改数据库的状态
//            DeviceMapper deviceMapper = (DeviceMapper) NettyClientSington.beanFactory.getBean("deviceMapper");
//            List<Device> deviceList = deviceMapper.select();
//            Set<String> onLineDevices = DemoUdpNettyServerHandler.senderMap.keySet();
//            for (Device device : deviceList) {
//                if (!onLineDevices.contains(device.getDevice()) && device.getState().equals(DeviceStateEnum.NORMAL.getType())){
//                    device.setState(DeviceStateEnum.UN_NORMAL.getType());
//                    deviceMapper.updateState(device);
//                }
//            }

        }
    }

    /**
     * 自修复 接收机
     * @param response
     * @param bean
     */
    private void repairDevice_jieshou(String response, BaseBean bean) {
        ZuWangAutoCheckFromJSRes zuWangAutoCheckFromJSRes = JSONUtil.toBean(response, ZuWangAutoCheckFromJSRes.class);

        ConfigFileUtil configFileUtil = (ConfigFileUtil) NettyClientSington.beanFactory.getBean("configFileUtil");

        List<ZuWangAutoCheckFromJSRes> allList = configFileUtil.readAutoCheck_jieshou();
        //数据库中的数据
        ZuWangAutoCheckFromJSRes dbAutoCheck = allList.get(0);
        //返回的错误的列表
        List<ZuWangAutoCheckFromJSRes.Info> info = zuWangAutoCheckFromJSRes.getInfo();
        //比对
        for (ZuWangAutoCheckFromJSRes.Info dblsInfo : dbAutoCheck.getInfo()) {
            for (ZuWangAutoCheckFromJSRes.Info lsInfo : info) {
                //去修改数据库里的数据
                if (dblsInfo.getModule().equals(lsInfo.getModule())) {
                    BeanUtils.copyProperties(lsInfo, dblsInfo);
                }
            }
        }

        List<ZuWangAutoCheckFromJSRes> list = new ArrayList<>();
        list.add(dbAutoCheck);
        //存入txt
        ConfigFileUtil.saveFile(configFileUtil.autoCheck_jieshou_loc, list);

        SendWebSocketInfo sendWebSocketInfo = new SendWebSocketInfo();
        sendWebSocketInfo.setTranstype(bean.getTranstype());
        sendWebSocketInfo.setUniStr(String.valueOf(UUID.randomUUID()));
        //向前端发送消息
        sendInfo(sendWebSocketInfo);
    }

    /**
     * 自修复 远程控制装置
     * @param response
     * @param bean
     */
    private void repairDevice_remote(String response, BaseBean bean) {
        ZuWangAutoCheckFromJSRes zuWangAutoCheckFromJSRes = JSONUtil.toBean(response, ZuWangAutoCheckFromJSRes.class);

        ConfigFileUtil configFileUtil = (ConfigFileUtil) NettyClientSington.beanFactory.getBean("configFileUtil");

        List<ZuWangAutoCheckFromJSRes> allList = configFileUtil.readAutoCheck_jieshou();
        //数据库中的数据
        ZuWangAutoCheckFromJSRes dbAutoCheck = allList.get(0);
        //返回的错误的列表
        List<ZuWangAutoCheckFromJSRes.Info> info = zuWangAutoCheckFromJSRes.getInfo();
        //比对
        for (ZuWangAutoCheckFromJSRes.Info dblsInfo : dbAutoCheck.getInfo()) {
            for (ZuWangAutoCheckFromJSRes.Info lsInfo : info) {
                //去修改数据库里的数据
                if (dblsInfo.getModule().equals(lsInfo.getModule())) {
                    BeanUtils.copyProperties(lsInfo, dblsInfo);
                }
            }
        }

        List<ZuWangAutoCheckFromJSRes> list = new ArrayList<>();
        list.add(dbAutoCheck);
        //存入txt
        ConfigFileUtil.saveFile(configFileUtil.autoCheck_remote_loc, list);

        SendWebSocketInfo sendWebSocketInfo = new SendWebSocketInfo();
        sendWebSocketInfo.setTranstype(bean.getTranstype());
        sendWebSocketInfo.setUniStr(String.valueOf(UUID.randomUUID()));
        //向前端发送消息
        sendInfo(sendWebSocketInfo);
    }

    /*
     获取自检测数据 接收
     */
    private void updapteAutoCheck_jieshou(String response, BaseBean bean) {

        ConfigFileUtil configFileUtil = (ConfigFileUtil) NettyClientSington.beanFactory.getBean("configFileUtil");
        ZuWangAutoCheckFromJSRes zuWangAutoCheckFromJSRes = JSONUtil.toBean(response, ZuWangAutoCheckFromJSRes.class);
        List<ZuWangAutoCheckFromJSRes> list = new ArrayList<>();
        list.add(zuWangAutoCheckFromJSRes);
        //存入txt
        ConfigFileUtil.saveFile(configFileUtil.autoCheck_jieshou_loc, list);

        SendWebSocketInfo sendWebSocketInfo = new SendWebSocketInfo();
        sendWebSocketInfo.setTranstype(bean.getTranstype());
        sendWebSocketInfo.setUniStr(String.valueOf(UUID.randomUUID()));
        //向前端发送消息
        sendInfo(sendWebSocketInfo);
    }

    /**
     * 获取自接收数据 远程
     *
     * @param response
     * @param bean
     */
    private void updapteAutoCheck_remoteControl(String response, BaseBean bean) {
        ZuWangAutoCheckFromJSRes zuWangAutoCheckFromJSRes = JSONUtil.toBean(response, ZuWangAutoCheckFromJSRes.class);
        List<ZuWangAutoCheckFromJSRes> list = new ArrayList<>();
        list.add(zuWangAutoCheckFromJSRes);
        ConfigFileUtil configFileUtil = (ConfigFileUtil) NettyClientSington.beanFactory.getBean("configFileUtil");
        //存入txt
        ConfigFileUtil.saveFile(configFileUtil.autoCheck_remote_loc, list);

        SendWebSocketInfo sendWebSocketInfo = new SendWebSocketInfo();
        sendWebSocketInfo.setTranstype(bean.getTranstype());
        sendWebSocketInfo.setUniStr(String.valueOf(UUID.randomUUID()));
        //向前端发送消息
        sendInfo(sendWebSocketInfo);
    }

    private void sendInfo(Object bean) {
        try {
            //从Spring容器获取websocket
//            ZuWangWebSocket zuWangWebSocket1 = (ZuWangWebSocket)applicationContext.getBean("zuWangWebSocket");
//            zuWangWebSocket1.sendInfo(JSONUtil.toJsonStr(bean));

            ZuWangWebSocket zuWangWebSocket = (ZuWangWebSocket) NettyClientSington.beanFactory.getBean("zuWangWebSocket");
            zuWangWebSocket.sendInfo(JSONUtil.toJsonStr(bean));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
